﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Project.Model.Rights;
using System.Linq;
using Project.Model;
using Microsoft.Office.Interop.Word;
using System.Data;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using System.Text;
using Project.Common;
using System.Net;

namespace Web
{
    public partial class _ExportPlantable : BasePage
    {
        // 接受的参数
        /// <summary>
        /// 项目 Id
        /// </summary>
        public Int32 PId { get; set; }

        /// <summary>
        /// 是否需要重新生成 PDF
        /// </summary>
        public bool IsRedo { get; set; }

        /// <summary>
        /// 是否是批处理
        /// </summary>
        public bool IsBatPDF { get; set; }

        /// <summary>
        /// 转换结果
        /// </summary>
        public string BatPDFResult { get; set; }

        Indexbasictable indexbasictable;

        object doNotSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
        object Missing = Type.Missing;

        public void Page_Load(object sender, EventArgs e)
        {
            if (!IsBatPDF)
            { Int32 _id = 0; Int32.TryParse(base.QueryString("id"), out _id); PId = _id; }
            IsRedo = base.QueryString("redo") == "1";

            if (PId <= 0)
            {
                this.DoError("参数错误!");
            }

            #region 安全验证
            // 1.检查 cookies 是否登录.(防止修改参数提交)
            //      true:下一步; 
            //      false:提示 需要登录
            // 2.检查 是否是当前登录用户的提交的项目.
            //      true:下一步
            //      false:提示:权限不足
            // 3.获取项目,取得封皮模板,替换数据
            // 4.合并三个word

            //// 1.
            //HttpCookie cookie = Request.Cookies["kjt_jhxmglxt"];
            //if (cookie == null)
            //{
            //    this.DoError("请先登录!");
            //    return;
            //}
            //string userName = cookie["USERNAME"];
            //string passWord = cookie["UserPass"];
            //UserManager user = ManagerFactory.UserManagerManager.GetByUserName(userName);
            //if (user == null || user.UserPass != passWord)
            //{
            //    this.DoError("请先登录!");
            //    return;
            //}

            // 2
            //string userName = "mj0";
            //Indexbasictable indexbasictable = ManagerFactory.IndexbasictableManager.Get(PId);
            //if (indexbasictable == null || indexbasictable.USERNAME != userName)
            //{
            //    this.DoError("权限不足!");
            //    return;
            //}
            #endregion

            // 检测记录是否存在
            indexbasictable = ManagerFactory.IndexbasictableManager.Get(PId);
            if (indexbasictable == null)
            {
                this.DoError("记录不存在!");
            }

            #region 检查数据库记录

            #region 判断 pdf 是否需要重新转换
            // 如果已经存在 转换之后的 pdf 则不需要抓换,直接打开
            // word 转化 pdf 的时候不能是中文你名 最后打开的是中文
            // 保证 Jhname 和 Itemname 中不能有 windows 命名规则中不能有的字符 \/:*? " <> |
            // 文件名不能超过 26 个中文( "高新技术研究与发展计划高新技术研究与发展计划发展计划"),否则会出现 "403 禁止访问". 但是英文可以超过.原因可能是中文会转换成编码之后是字符数加倍
            //string pdfCNPath = "~/@Export/" + this.fliterWindowName(indexbasictable.Jhname) + "-" + this.fliterWindowName(indexbasictable.Itemname) + "_项目申报书.pdf";
            //string pdfCNPath = "~/@Export/" + indexbasictable.Id + "-项目申报书.pdf";
            //string pdfCNPath = "~/@Export/" + indexbasictable.Id + "-"+ fliterWindowName(indexbasictable.Itemname) + "-项目申报书.pdf";
            string pdfCNPath = "~/@Export/" + indexbasictable.Id + "-" + fliterWindowName(indexbasictable.Itemname) + "-项目申报书.pdf";
            // 不带中文的文件名 只用于转换
            string pdfFilePath = "~/@Export/" + indexbasictable.Id + ".pdf";
            // 判断 pdf 是否需要重新转换:用户更新 word 的时候会更新 updatedate 字段,如果 updatedate 比 pdfexportdate 新则需要重新生成
            bool isRedoPdf = false;
            // 如果更新时间或者PDF转换时间为空,则转换
            isRedoPdf = indexbasictable.UpdateDate.HasValue && indexbasictable.PdfExportDate.HasValue;
            // 如果为 false ,再判断 UpdateDate 的时间是否比 PdfExportDate 新
            if (isRedoPdf)
                isRedoPdf = indexbasictable.UpdateDate.Value.CompareTo(indexbasictable.PdfExportDate.Value) > 0;
            // 如果 isRedoPdf = false (不需要重新转换),检测已经转换的 PDF 文件是否存在
            if (!IsRedo && File.Exists(Server.MapPath(pdfCNPath)))
            {
                this.DownloadPdf(pdfCNPath);
            }
            #endregion

            ShqUserManager shquserManager = ManagerFactory.ShqUserManagerManager.GetByIndexbasictable(indexbasictable);
            if (shquserManager == null)
            {
                this.DoError("不存在名称为 " + indexbasictable.Itemname + " 的记录!");
            }

            Plantable plantable = ManagerFactory.PlantableManager.GetByName(shquserManager.Jhname);
            if (plantable == null)
            {
                this.DoError("计划细分表中不存在名称为 " + indexbasictable.Jhname + " 的计划!");
            }

            Itemtable itemTable = ManagerFactory.ItemtableManager.GetByShqUserManager(shquserManager);
            if (itemTable == null)
            {
                this.DoError("项目表中不存在名称为 " + indexbasictable.Jhname + " 的项目!");
            }

            UserManager userManager = ManagerFactory.UserManagerManager.GetByUserName(indexbasictable.USERNAME);
            if (userManager == null)
            {
                this.DoError("不存在名称为 " + indexbasictable.USERNAME + " 的用户!");
            }

            string imgUrl = "http://10.10.1.21:8001/" + "Barcode.aspx?BarcodeType=EAN13&Data=1234567890128&CopyrightText=&BarWidth=2&Height=80";
            string path = Server.MapPath("~/@Export/Barcode/");
            //string fileName = indexbasictable.Id.ToString();
            string fileName = "0";
            if (!File.Exists(path + fileName + ".jpg"))
            {
                string imgFilePath = SaveImageFromWeb(imgUrl, path, fileName);
            }

            #endregion

            //为防止本方法调用多次时发生错误,必须停止acrodist.exe进程
            // KillPrecess("acrodist");

            // 3 
            #region 合并

            #region 生成word 封皮

            // 模板Word文件路径：根据申请的计划类别确定  /@Template/计划类别名称.doc
            string template1FilePath = "~/@Template/" + plantable.Jhmb;
            if (!File.Exists(Server.MapPath(template1FilePath)))
            {
                this.DoError("模板文件不存在!位置在:" + template1FilePath);
            }

            // 检测是否存在 文件夹,如果文件夹不存在,会报错
            if (!Directory.Exists(Server.MapPath("~/@Export")))
            {
                Directory.CreateDirectory(Server.MapPath("~/@Export"));
            }

            // 封皮 Word文件保存路径
            string template1SaveFilePath = "~/@Export/" + indexbasictable.Id + "-0.doc";

            DataTable dtIndexbasictable = base.ConvertToDataTable<Indexbasictable>(indexbasictable, true);
            DataTable dtItemtable = base.ConvertToDataTable<Itemtable>(itemTable, true);
            DataTable dtUserManager = base.ConvertToDataTable<UserManager>(userManager, true);
            DataTable dtPlantable = base.ConvertToDataTable<Plantable>(plantable, true);
            DataTable dtShqUserManager = base.ConvertToDataTable<ShqUserManager>(shquserManager, true);

            DataTable dt = base.UniteDataTable(dtIndexbasictable, dtItemtable);
            dt = base.UniteDataTable(dt, dtUserManager);
            dt = base.UniteDataTable(dt, dtPlantable);
            dt = base.UniteDataTable(dt, dtShqUserManager);

            #endregion

            #region 生成word 用户基本信息
            //// 模板Word文件路径：根据申请的类型确定 
            //string template2FilePath = "~/@Template/" + "JhName" + dPlantable.Id + "-2.doc";
            //if (!File.Exists(Server.MapPath(template2FilePath)))
            //{
            //    this.DoError("模板文件不存在!位置在:" + template2FilePath);
            //    return;
            //}

            //// 新Word文件保存路径
            //string template2SaveFilePath = "~/@Export/JhName" + dPlantable.Id + "-2.doc";

            //this.CreatWord<Indexbasictable>(template2FilePath, dt, template2SaveFilePath, indexbasictable);
            #endregion

            #region 获取 用户提交 doc 地址
            string word3path = string.Empty;
            // 由于还有个经费文件: 申报: itemTable.Id ; 合同书: itemTable.Id_001 ; 经费预算书: itemTable.Id_002
            if (itemTable == null)
            {
                this.DoError("PID : " + PId);
                return;
            }
            Files filesModel = ManagerFactory.FileManager.GetByName(itemTable.Id.ToString());
            if (filesModel != null)
            {
                word3path = "~/shenbaory/admin/" + filesModel.Fpath + "/" + filesModel.Fname;
                if (word3path.IndexOf(".wps") >= 0)
                {
                    ExecJsAjax("alert('系统不支持WPF文档，请重新提交WORD文档')",Page);
                }
            }
            else
            {
                this.DoError("用户还未提交 Word");
            }
            if (!File.Exists(Server.MapPath(word3path)))
            {
                this.DoError("用户提交 Word 不存在!位置在:" + word3path);
            }
            if (word3path.ToLower().Trim().EndsWith("wps"))
            {
                // WPS 可以用 Word 打开,并且可以转换成 PDF ,暂时注释
                //this.DoError("WPS 格式不兼容,必须是 Word 格式! 位置在:" + word3path);
            }
            #endregion

            // 生成 封皮 Word
            this.CreatWord<Indexbasictable>(template1FilePath, dt, template1SaveFilePath, indexbasictable);

            // 合并
            string[] files = new string[] { template1SaveFilePath, word3path };
            string MergerWordFilepath = pdfFilePath.Substring(0, pdfFilePath.Length - 3) + "doc";
            MergerWord(files, MergerWordFilepath);

            #endregion

            // 4 转换 pdf
            #region 转换 pdf
            //WordConvert(Server.MapPath(MergerWordFilepath));
            // 返回中文的pdf,但是中文的名称不能正常转换,所以把保存的 pdf 文件当作参数传入
            if (File.Exists(Server.MapPath(MergerWordFilepath)))
            {
                WordConvert(Server.MapPath(MergerWordFilepath), Server.MapPath(pdfCNPath));
            }
            else
            {
                this.DoError("要转换的 Word 不存在! 位置在 " + Server.MapPath(MergerWordFilepath));
            }

            // 删除临时文件 封皮 Word 以及 合并之后的 Word
            if (File.Exists(Server.MapPath(template1SaveFilePath)))
                File.Delete(Server.MapPath(template1SaveFilePath));
            //if (File.Exists(Server.MapPath(MergerWordFilepath)))
            //    File.Delete(Server.MapPath(MergerWordFilepath));
            #endregion

            // 更新 PdfExportDate
            indexbasictable.PdfExportDate = DateTime.Now;
            ManagerFactory.IndexbasictableManager.Update(indexbasictable);

            // 5 弹出 pdf
            #region 弹出 pdf
            // 如果直接跳转,会发生直接在IE中打开 pdf 源码
            // 如果在 IIS 中添加 pdf 的 MIME 之后,是根据用户本地的 pdf 类型设置(是直接打开还是先下载再打开) 来打开
            this.DownloadPdf(pdfCNPath);

            #endregion

        }

        #region 解决文件下载时文件名的中文乱码  http://www.cnblogs.com/ciznx/articles/1793695.html

        /// <summary>
        /// 弹出 pdf 下载
        /// </summary>
        /// <param name="pdfCNPath"></param>
        private void DownloadPdf(string pdfCNPath)
        {
            string path = Server.MapPath(pdfCNPath);//获取客户端请求的文件的物理地址
            if (File.Exists(path) && !IsBatPDF)
            {
                string fileName = System.IO.Path.GetFileName(path);   // 获取文件的名字
                if (System.Web.HttpContext.Current.Request.UserAgent.Contains("MSIE") || System.Web.HttpContext.Current.Request.UserAgent.Contains("msie"))
                {
                    // 如果客户端使用 Microsoft Internet Explorer，则需要编码
                    fileName = ToHexString(fileName);     // 如果使用  fileName =Server.UrlEncode(fileName);  则会出现上文中出现的情况
                }
                System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                System.Web.HttpContext.Current.Response.ContentType = "application/pdf";
                System.Web.HttpContext.Current.Response.WriteFile(path);
                System.Web.HttpContext.Current.Response.End();
            }
        }

        /// <summary>
        /// 为字符串中的非英文字符编码
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToHexString(string s)
        {
            char[] chars = s.ToCharArray();
            StringBuilder builder = new StringBuilder();
            for (int index = 0; index < chars.Length; index++)
            {
                bool needToEncode = NeedToEncode(chars[index]);
                if (needToEncode)
                {
                    string encodedString = ToHexString(chars[index]);
                    builder.Append(encodedString);
                }
                else
                {
                    builder.Append(chars[index]);
                }
            }

            return builder.ToString();
        }

        /// <summary>
        ///指定 一个字符是否应该被编码
        /// </summary>
        /// <param name="chr"></param>
        /// <returns></returns>
        private static bool NeedToEncode(char chr)
        {
            string reservedChars = "$-_.+!*'(),@=&";

            if (chr > 127)
                return true;
            if (char.IsLetterOrDigit(chr) || reservedChars.IndexOf(chr) >= 0)
                return false;

            return true;
        }

        /// <summary>
        /// 为非英文字符串编码
        /// </summary>
        /// <param name="chr"></param>
        /// <returns></returns>
        private static string ToHexString(char chr)
        {
            UTF8Encoding utf8 = new UTF8Encoding();
            byte[] encodedBytes = utf8.GetBytes(chr.ToString());
            StringBuilder builder = new StringBuilder();
            for (int index = 0; index < encodedBytes.Length; index++)
            {
                builder.AppendFormat("%{0}", Convert.ToString(encodedBytes[index], 16));
            }
            return builder.ToString();
        }

        #endregion

        /// <summary>
        /// 去除 windows 命名规则中不能有的字符 \/:*? " <> |
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private string fliterWindowName(string p)
        {
            string str = "\\/:*?\"<>|";
            for (int i = 0; i < str.Length; i++)
            {
                p = p.Replace(str[i].ToString(), "");
            }
            return p;
        }

        /// <summary>
        /// 合并Word
        /// </summary>
        private void MergerWord(string[] files, string newFilePath)
        {
            // 以第一个文件为基础,循环,将Word中的内容粘贴到第一个模板中,       这样会出现用户的格式发生变化
            string basefile = files[0];
            //// 以最后一个word为基础,一次将word中的内容插入到最后一个word中,        这样可以保证用户的格式不变(居然会出现有的 Word 在 firstDoc.Content.Words.First.Paste() 出现命令失败的异常)
            //string basefile = files[files.Length - 1];


            ApplicationClass appWord;
            DocumentClass firstDoc;
            // 读取初始 Word.
            appWord = new Microsoft.Office.Interop.Word.ApplicationClass();
            appWord.Visible = false;
            object objTrue = true;
            object objFalse = false;
            object objDocType = WdDocumentType.wdTypeDocument;
            object objTemplate = Server.MapPath(basefile);
            // Word 中出现乱码,会抛出异常
            // Word 无法读取文档，文档可能损坏。
            //请尝试下列方法:
            //* 打开并修复文件。
            //* 用文本恢复转换器打开文件。 

            try { 
                firstDoc = (DocumentClass)appWord.Documents.Add(ref objTemplate, ref objFalse, ref objDocType, ref objTrue);

                if (firstDoc == null)
                {
                    this.DoError("文件不存在!位置在:" + objTemplate);
                }

                try
                {
                    //定义分页
                    object pBreak = (int)WdBreakType.wdSectionBreakNextPage;
                    // 以第一个文件为基础,循环,将Word中的内容粘贴到第一个模板中
                    for (int i = 1; i < files.Length; i++)
                    //// 以最后一个文件为基础,从后循环,将Word中的内容粘贴到最后一个模板中
                    //for (int i = files.Length - 2; i >= 0; i--)
                    {
                        if (File.Exists(Server.MapPath(files[i])))
                        {
                                        #region 打开文档
                        object objTemplate2 = Server.MapPath(files[i]);
                        DocumentClass tempdoc = (DocumentClass)appWord.Documents.Add(ref objTemplate2, ref objFalse, ref objDocType, ref objTrue);
                        #endregion

                            try
                            {
                                // 以第一个文件为基础,循环,将Word中的内容粘贴到第一个模板中
                                //插入分页符
                                firstDoc.Content.Words.Last.InsertBreak(ref pBreak);
                                //将doc3内容粘贴到doc最后面
                                tempdoc.Content.Copy();
                                firstDoc.Content.Words.Last.Paste();

                                //// 以最后一个文件为基础,从后循环,将Word中的内容粘贴到最后一个模板中
                                ////将doc3内容粘贴到doc最后面
                                //tempdoc.Content.Words.Last.InsertBreak(ref pBreak);
                                //tempdoc.Content.Copy();
                                ////插入分页符
                                //firstDoc.Content.Words.First.InsertBreak(ref pBreak);
                                //firstDoc.Content.Words.First.Paste();
                            }
                            catch (Exception ex)
                            {
                                //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                                this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
                            }
                            finally
                            {
                                if (tempdoc != null)
                                {
                                    ((_Document)tempdoc).Close(ref doNotSaveChanges, ref Missing, ref Missing);
                                    tempdoc = null;
                                }
                            }
                        }
                    }

                    //第四步 生成word
                    object filename = Server.MapPath(newFilePath);
                    firstDoc.SaveAs(ref filename, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing);
                }
                catch (Exception ex)
                {
                    //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                    this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
                }
                finally
                {
                    if (firstDoc != null)
                    {
                        firstDoc.Close(ref doNotSaveChanges, ref Missing, ref Missing);
                        firstDoc = null;
                    }
                    if (appWord != null)
                    {
                        ((_Application)appWord).Quit(ref Missing, ref Missing, ref Missing);
                        appWord = null;
                    }
                }
            }
            catch (Exception ex)
            {
                //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
            }
            finally
            {
                //if (firstDoc != null)
                //{
                //    firstDoc.Close(ref doNotSaveChanges, ref Missing, ref Missing);
                //    firstDoc = null;
                //}
                if (appWord != null)
                {
                    ((_Application)appWord).Quit(ref Missing, ref Missing, ref Missing);
                    appWord = null;
                }
            }


        }

        /// <summary>
        /// 根据模板生成Word
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_tempFilePath"></param>
        /// <param name="t"></param>
        /// <param name="_newFilePath"></param>
        private void CreatWord<T>(string _tempFilePath, DataTable dt, string _newFilePath, T t)
        {
            // 模板Word文件路径：根据申请的类型确定 
            string tempFilePath = _tempFilePath;

            // 新Word文件保存路径
            string newFilePath = _newFilePath;

            // 创建一个名为WordApp的组件对象 
            Application WordApp = new ApplicationClass();
            //必须设置为不可见
            WordApp.Visible = false;
            //创建以tempFilePath为模板的文档
            object oTemplate = HttpContext.Current.Server.MapPath(tempFilePath);
            Document WordDoc = WordApp.Documents.Add(ref oTemplate, ref Missing, ref Missing, ref Missing);

            try
            {
                WordDoc.Activate();

                #region 替换模板文件中的标签(采用书签名称(表对应的类名_字段对应的属性名)与字段一一对应实现自动替换)
                // 科技支撑计划 会转换 5 次,但只有一个书签
                bool IsAddBarcode = false;

                Type type = t.GetType();
                foreach (Bookmark bm in WordDoc.Bookmarks)
                {
                    // ConvertToDataTable 函数中已经实现将 类名添加到属性之前
                    // DataTable 中对应的 列名称
                    string columnName = bm.Name;

                    // 特殊类型书签( DateTime 类型)
                    string[] strings = columnName.Split('_');
                    if (strings.Length >= 2)
                        columnName = (strings[0] + "_" + strings[1]).ToLower();
                    if (dt.Columns.Contains(columnName) && dt.Rows[0][columnName] != null)
                    {
                        string value = dt.Rows[0][columnName].ToString();
                        if (dt.Columns[columnName].DataType.Name == typeof(DateTime).Name)
                        {
                            // DateTime 类型
                            #region DateTime 类型

                            if (strings.Length == 3)
                            {
                                // 自定义时间格式: 表名_字段名_自定义格式
                                if (Validator.IsDateTime(value))
                                    value = ((DateTime)dt.Rows[0][columnName]).ToString(strings[2]);
                            }
                            else
                            {
                                // 一般时间格式 只显示日期
                                if (Validator.IsDateTime(value))
                                    value = ((DateTime)dt.Rows[0][columnName]).ToShortDateString();
                            }

                            #endregion
                        }
                        else
                        {
                            string _column = (typeof(Itemtable).Name + "_" + PropertyNameHelper.Resolve<Itemtable>(d => d.Jymj));
                            if (columnName.ToLower() == _column.ToLower())
                            {
                                // 建议密集 Itemtable_Jymj √ ☑ □ 
                                #region 建议密集
                                // 第三个数组必须是 int
                                if (strings.Length == 3 && Validator.IsInt(strings[2]))
                                {
                                    // value 为空的时候, Parse 会报错
                                    // 第三个数组和 value 的值必须是在 EnumItemTableJYMJ 中的.并且 Parse strings[2] 之后的 Enum 的 值 == 数据库中的值
                                    if (Enum.IsDefined(typeof(EnumItemTableJYMJ), value) && Enum.IsDefined(typeof(EnumItemTableJYMJ), int.Parse(strings[2])) && (int)Enum.Parse(typeof(EnumItemTableJYMJ), value) == int.Parse(strings[2]))
                                        value = "☑";
                                    else
                                        //value = "□";
                                        // 跳出:否则书签会被 书签中的值替换
                                        continue;
                                }
                                #endregion
                            }

                        }

                        #region Enum 类型 如:"青海省自然科学基金项目申报书" 中的 资质类别
                        // 不知道如何通过名称获取到 Enum,暂时写死
                        //else if (strings.Length == 4 &&strings[2].ToLower() == "enum" && Validator.IsInt(strings[3]))
                        // 书签形式 tablename_columnname_enum_value(int) 
                        if (strings.Length == 4 && strings[2].ToLower() == "enum" && Validator.IsInt(strings[3]))
                        {
                            if (columnName.ToLower() == "ItemTable_zzlb".ToLower())
                            {
                                if (Enum.IsDefined(typeof(EnumItemTable_Zzlb), value) && Enum.IsDefined(typeof(EnumItemTable_Zzlb), int.Parse(strings[3])) && (int)Enum.Parse(typeof(EnumItemTable_Zzlb), value) == int.Parse(strings[strings.Length - 1]))
                                    value = "☑";
                                else
                                    //value = "□";
                                    // 跳出:否则书签会被 书签中的值替换
                                    continue;
                            }
                            if (columnName.ToLower() == "ItemTable_Jhname".ToLower())
                            {
                                if (Enum.IsDefined(typeof(EnumItemTable_Jhname), value) && Enum.IsDefined(typeof(EnumItemTable_Jhname), int.Parse(strings[3])) && (int)Enum.Parse(typeof(EnumItemTable_Jhname), value) == int.Parse(strings[strings.Length - 1]))
                                    value = "☑";
                                else
                                    //value = "□";
                                    // 跳出:否则书签会被 书签中的值替换
                                    continue;
                            }
                        }
                        #endregion

                        bm.Select();
                        WordApp.Selection.TypeText(value.ToString());
                    }
                    else if (bm.Name.ToLower() == "Barcode".ToLower() && !IsAddBarcode)
                    {
                        // 加入条形码
                        // 1.在服务器上生成条形码图片
                        // 2.将生成的条形码加入到 word 中
                        string imgUrl = "http://10.10.1.21:8001/" + "Barcode.aspx?BarcodeType=EAN13&Data=1234567890128&CopyrightText=&BarWidth=2&Height=80";
                        string path = Server.MapPath("~/@Export/Barcode/");
                        string fileName = indexbasictable.Id.ToString();
                        string imgFilePath = path + fileName + ".jpg";
                        if (!File.Exists(path + fileName + ".jpg"))
                        {
                            SaveImageFromWeb(imgUrl, path, fileName);
                        }
                        // 检查图片是否存在
                        if (!string.IsNullOrEmpty(imgFilePath) && File.Exists(imgFilePath))
                        {
                            bm.Select();
                            InlineShape shape = WordApp.Selection.InlineShapes.AddPicture(imgFilePath, ref Missing, ref Missing, ref Missing);
                            // 设置图片大小
                            //shape.Height = WordApp.InchesToPoints((float)0.5);
                            //shape.Width = WordApp.InchesToPoints((float)0.5); 
                        }
                        IsAddBarcode = true;
                    }

                }

                #endregion

                //保存为新文件
                object oNewFileName = HttpContext.Current.Server.MapPath(newFilePath);
                WordDoc.SaveAs(ref oNewFileName, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing,
                 ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing);
            }
            catch (Exception ex)
            {
                //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
            }
            finally
            {
                if (WordDoc != null)
                {
                    ((_Document)WordDoc).Close(ref doNotSaveChanges, ref Missing, ref Missing);
                    WordDoc = null;
                }
                if (WordApp != null)
                {
                    ((_Application)WordApp).Quit(ref Missing, ref Missing, ref Missing);
                    WordApp = null;
                }
            }

        }

        /// 从网上搜索到下面这个办法，也是比较简单的。
        /// 前提条件：
        ///（1）安装虚拟打印机：进入WINDOWS的控制面板，进入打印机,点击"添加打印机"图标，在安装对话框上"按一步"，出现选择打印机时，在制造商一栏中选择"Generic"，在打印机一栏中，选择"MS Publisher Color Printer"，然后一路按下一步，知道安装结束。以下代码并没有提供当前的打印机，而是使用系统默认的，即设置的"MS Publisher Color Printer"。
        ///（2）必须添加引用Acrobat Distiller与WORD，可以从COM组件中添加。
        /// http://www.cnblogs.com/lne818/archive/2008/10/24/1318599.html
        /// <summary>
        /// 在WebForm下转换.将Word转换成pdf
        /// </summary>
        /// <param name="docFilePath">Word 文件路劲( Server.Math() )</param>
        public void WordConvert(string _docFilePath, string pdfSavePath)
        {
            //c#根据绝对路径获取 带后缀文件名、后缀名、文件名。

            //string fileStr ="F:\test\Default.aspx";
            string fileStr = _docFilePath;
            string filename = System.IO.Path.GetFileName(fileStr);//文件名 “Default.aspx”
            string extension = System.IO.Path.GetExtension(fileStr);//扩展名 “.aspx”
            string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(fileStr);// 没有扩展名的文件名 “Default”

            string docFilePath = _docFilePath;
            string _psFilePath = ReplaceFileSuffix(_docFilePath, "ps");
            //string _pdfFilePath = ReplaceFileSuffix(_docFilePath, "pdf");
            string _pdfFilePath = pdfSavePath;
            string _strJobOptions = "";
            string logFilePath = _pdfFilePath.Substring(0, _pdfFilePath.Length - 3) + "log";

            Microsoft.Office.Interop.Word.ApplicationClass word = new Microsoft.Office.Interop.Word.ApplicationClass();
            Type wordType = word.GetType();
            Microsoft.Office.Interop.Word.Documents docs = word.Documents;
            Type docsType = docs.GetType();
            object objDocName = docFilePath;
            Microsoft.Office.Interop.Word.Document doc = (Microsoft.Office.Interop.Word.Document)docsType.InvokeMember("Open", System.Reflection.BindingFlags.InvokeMethod, null, docs, new Object[] { objDocName, true, true });
           // KillProcess("acrodist");
            try
            {
                //打印输出到指定文件
                Type docType = doc.GetType();
                object printFileName = _psFilePath;
                docType.InvokeMember("PrintOut", System.Reflection.BindingFlags.InvokeMethod, null, doc, new object[] { false, false, Microsoft.Office.Interop.Word.WdPrintOutRange.wdPrintAllDocument, printFileName });
                //wordType.InvokeMember("Quit", System.Reflection.BindingFlags.InvokeMethod, null, word, null);
                //((_Document)doc).Close(ref doNotSaveChanges, ref Missing, ref Missing);
                //doc = null;
                //((_Application)word).Quit(ref Missing, ref Missing, ref Missing);
                //word = null;

                //引用将PS转换成PDF的对象
                ACRODISTXLib.PdfDistillerClass pdf = new ACRODISTXLib.PdfDistillerClass();
                string psFilePath = _psFilePath;
                string pdfFilePath = _pdfFilePath;
                string strJobOptions = _strJobOptions;
                pdf.FileToPDF(psFilePath, pdfFilePath, strJobOptions);

            }
            catch (Exception ex)
            {
                //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
            }
            finally
            {
                if (doc != null)
                {
                    ((_Document)doc).Close(ref doNotSaveChanges, ref Missing, ref Missing);
                    doc = null;
                }
                if (word != null)
                {
                    ((_Application)word).Quit(ref Missing, ref Missing, ref Missing);
                    word = null;
                }
            }

            // 删除 临时文件 ps log
            #region MyRegion
            string psFile = _psFilePath;
            if (File.Exists(psFile))
                File.Delete(psFile);
            string logFile = logFilePath;
            if (File.Exists(logFile))
                File.Delete(logFile);
            #endregion

            //为防止本方法调用多次时发生错误,必须停止acrodist.exe进程
            KillPrecess("acrodist");
            KillPrecess("acrotray");
            #region MyRegion
            //foreach (Process proc in System.Diagnostics.Process.GetProcesses())
            //{
            //    int begpos;
            //    int endpos;

            //    string sProcName = proc.ToString();
            //    begpos = sProcName.IndexOf("(") + 1;
            //    endpos = sProcName.IndexOf(")");

            //    sProcName = sProcName.Substring(begpos, endpos - begpos);

            //    if (sProcName.ToLower().CompareTo("acrodist") == 0)
            //    {
            //        proc.Kill();
            //        break;
            //    }
            //} 
            #endregion
        }

        /// <summary>
        /// 为防止本方法调用多次时发生错误,必须停止acrodist.exe进程
        /// 参考页面 http://blog.csdn.net/hack8/archive/2009/02/05/3863483.aspx
        /// </summary>
        /// <param name="processName"></param>
        public void KillPrecess(string processName)
        {
           
            //定义进程
            System.Diagnostics.Process myproc = new System.Diagnostics.Process();
            try
            {
                //获取选择的进程名称
                string proname = processName;
                //从所有的进程中获取选择的进程
           
                foreach (Process pro in Process.GetProcessesByName(proname))
                    {
                        //判断是否是系统的主要进程，如果是则不能结束
                       
                        if (!pro.CloseMainWindow())
                        {
                            //lblMsg.Text = this.DropPro.SelectedValue + "进程被结束！";
                            //结束进程
                            pro.Kill();
                        }
                    }

            }
            catch (Exception err)
            {
                throw new System.Exception(err.Message);
            }

        }
        public void KillProcess(string processName)
        {

            //定义进程
            System.Diagnostics.Process myproc = new System.Diagnostics.Process();
            try
            {
                //获取选择的进程名称
                string proname = processName;
                //从所有的进程中获取选择的进程
                Process[] process = Process.GetProcessesByName(proname);

                if (process.Length > 0)
                {
                    foreach (Process pro in process)
                    {
                        //判断是否是系统的主要进程，如果是则不能结束
                        pro.EnableRaisingEvents = true;
                        if (!pro.HasExited)
                        {
                            if (!pro.CloseMainWindow())
                            {
                                //lblMsg.Text = this.DropPro.SelectedValue + "进程被结束！";
                                //结束进程
                                pro.Kill();
                            }
                        }
                    }
                }
            }
            catch (Exception err)
            {
                throw new System.Exception(err.Message);
            }

        }

        /// <summary>
        /// 替换链接地址后缀
        /// </summary>
        /// <param name="url"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public string ReplaceFileSuffix(string path, string suffix)
        {
            Uri url = new Uri(path);
            string fileName = url.Segments[url.Segments.Length - 1];
            string fileNameSuffix = fileName.Split('.')[fileName.Split('.').Length - 1];
            Uri newUrl = new Uri(url.ToString().Replace(fileName, fileName.Split('.')[0] + "." + suffix));
            string newUrlStr = newUrl.ToString();
            if (!string.IsNullOrEmpty(newUrl.Query))
            {
                newUrlStr = newUrlStr.Replace(newUrl.Query, "");
            }
            if (newUrl.Scheme == "file")
            {
                newUrlStr = newUrlStr.Replace("file:///", "");
            }
            return newUrlStr;
        }

        /// <summary>
        /// Word按页读取内容
        /// </summary>
        /// <param name="page">页数</param>
        /// <param name="isHtml">html或纯文本</param>
        /// <returns></returns>
        /// http://hi.baidu.com/alocne
        //public string ReadPage(int page, bool isHtml, Document oDoc)
        //{
        //    object Missing = Type.Missing;
        //    object objWhat = WdGoToItem.wdGoToPage;
        //    object objWhich = WdGoToDirection.wdGoToAbsolute;

        //    object objPage = page;
        //    Range range1 = oDoc.GoTo(ref objWhat, ref objWhich, ref objPage, ref Missing);
        //    Range range2 = range1.GoToNext(WdGoToItem.wdGoToPage);

        //    object objStart = range1.Start;
        //    object objEnd = range2.Start;
        //    if (range1.Start == range2.Start)
        //        objEnd = oDoc.Characters.Count;//最后一页
        //    oDoc.Range(ref objStart, ref objEnd).Copy();

        //    if (isHtml)
        //    {
        //        MemoryStream stream = Clipboard.GetData("Html Format") as MemoryStream;
        //        stream.Position = 0;//解决从剪切板复制中文内容乱码的问题www.xuehi.com
        //        byte[] bytes = new byte[stream.Length];
        //        stream.Read(bytes, 0, (int)stream.Length);

        //        return Encoding.UTF8.GetString(bytes);
        //    }
        //    else
        //    {
        //        byte[] bytes = Encoding.Default.GetBytes((string)Clipboard.GetData(DataFormats.Text));

        //        return Encoding.GetEncoding("gb2312").GetString(bytes);
        //    }
        //}

        /// <summary>
        /// 发生错误的时候执行的操作
        /// </summary>
        /// <param name="p"></param>
        private void DoError(string p)
        {
            BatPDFResult = p;
            if (!IsBatPDF)
            { 
                if (!System.Web.HttpContext.Current.Request.IsLocal)
                    System.Web.HttpContext.Current.Response.Write("<script language=javascript>alert('" + p.Replace("\r\n", "").Replace("'", "\"") + "');opener=null;window.close();</script>");
                else
                    System.Web.HttpContext.Current.Response.Write("<script language=javascript>alert('" + p.Replace("\r\n", "").Replace("'", "\"") + "');</script>");
                System.Web.HttpContext.Current.Response.End();
            }
        }

        /// <summary>
        /// C# 获取外网图片并保存到相对应路径
        /// </summary>
        public string SaveImageFromWeb(string imgUrl, string path, string fileName)
        {
            //imgUrl = "http://" + HttpContext.Current.Request.Url.Authority + "/Barcode.aspx?BarcodeType=EAN13&Data=1234567890128&CopyrightText=&BarWidth=2&Height=80";
            imgUrl = "http://10.10.1.21:8001/" + "Barcode.aspx?BarcodeType=EAN13&Data=1234567890128&CopyrightText=&BarWidth=2&Height=80";
            string imgFilePath = string.Empty;
            if (path.Equals(""))
                throw new Exception("未指定保存文件的路径");

            string imgName = imgUrl.ToString().Substring(imgUrl.ToString().LastIndexOf("/") + 1);
            string defaultType = ".jpg";
            string[] imgTypes = new string[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };
            string imgType = imgUrl.ToString().Substring(imgUrl.ToString().LastIndexOf("."));
            foreach (string it in imgTypes)
            {
                if (imgType.ToLower().Equals(it))
                    break;
                if (it.Equals(".bmp"))
                    imgType = defaultType;
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgUrl);
            request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
            request.Timeout = 1000 * 60 * 2;

            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();

            if (response.ContentType.ToLower().StartsWith("image/"))
            {
                byte[] arrayByte = new byte[1024];
                int imgLong = (int)response.ContentLength;
                int l = 0;

                if (fileName == "")
                    fileName = imgName;

                // 检测是否存在 文件夹,如果文件夹不存在,会报错
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                imgFilePath = path + fileName + imgType;
                FileStream fso = new FileStream(imgFilePath, FileMode.Create);
                while (l < imgLong)
                {
                    int i = stream.Read(arrayByte, 0, 1024);
                    fso.Write(arrayByte, 0, i);
                    l += i;
                }

                fso.Close();
                stream.Close();
                response.Close();
            }
            return imgFilePath;
        }

        #region 测试无关代码

        /// <summary>
        /// C#向Word文档中插入条形码 (ActiveX 形式)
        /// 打开 添加条形码的 word 会有安全警告提示 
        /// http://www.cnblogs.com/waxdoll/archive/2009/09/23/Add_OLE_Control_In_Word_Document.html
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddBarCodeControl_Click(object sender, EventArgs e)
        {
            Microsoft.Office.Interop.Word.Application WordApp = null;
            Microsoft.Office.Interop.Word.Document WordDoc = null;
            object mValue = System.Reflection.Missing.Value;

            object objFileName = Server.MapPath("~/@Export/JhName123-1.doc");

            object objReadOnly = false;

            WordApp = new Microsoft.Office.Interop.Word.Application();

            WordDoc = WordApp.Documents.Open(
                  ref objFileName
                , ref mValue
                , ref objReadOnly
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
                , ref mValue
            );

            //object objOleControlType = "BARCODE.BarCodeCtrl.1";

            //object objLeft = 20;
            //object objTop = 20;
            //object objWidth = 200;
            //object objHeight = 50;

            //object comControl = WordDoc.Shapes.AddOLEControl(
            //      ref objOleControlType
            //    , ref objLeft
            //    , ref objTop
            //    , ref objWidth
            //    , ref objHeight
            //    , ref mValue
            //).OLEFormat.Object;


            //((BARCODELib.IBarCodeCtrl)comControl).Value = "S-102909211000001-12";

            //((BARCODELib.IBarCodeCtrl)comControl).Style = 7;

            //WordDoc.Save();

            try
            {
                WordDoc.Activate();

                foreach (Bookmark bm in WordDoc.Bookmarks)
                {
                    if (bm.Name == "tiaoxingma")
                    {
                        bm.Select();
                        //WordApp.Selection.InlineShapes.AddOLEControl(ref Missing,ref comControl);
                        WordApp.Selection.InlineShapes.AddPicture(Server.MapPath("~/@Export/Barcode/2365.jpg"), ref Missing, ref Missing, ref Missing);
                        break;
                    }
                }

                //保存为新文件
                object oNewFileName = HttpContext.Current.Server.MapPath("~/@Export/JhName123-2.doc");
                WordDoc.SaveAs(ref oNewFileName, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing,
                 ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing, ref Missing);
                //WordDoc.Save();
            }
            catch (Exception ex)
            {
                //捕捉异常，如果出现异常则清空实例，退出word,同时释放资源
                this.DoError("Messageex:" + ex.Message + " StackTrace:" + ex.StackTrace);
            }
            finally
            {
                if (WordDoc != null)
                {
                    ((_Document)WordDoc).Close(ref doNotSaveChanges, ref Missing, ref Missing);
                    WordDoc = null;
                }
                if (WordApp != null)
                {
                    ((_Application)WordApp).Quit(ref Missing, ref Missing, ref Missing);
                    WordApp = null;
                }
            }
        }

        #endregion

    }
}